package com.hhq.system.security.util;

import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import com.hhq.system.common.constant.SecurityConstants;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.concurrent.TimeUnit;

/**
 * <p>Description: 租户信息 </p>
 *
 * @author : xiaodong.yang
 * @date : 2024/6/28 10:04
 */
@Component
@RequiredArgsConstructor
public class TenantContextHolder {

    private final RedisTemplate<String, Object> redisTemplate;

    public void setTenant(Long tenantId) {
        JSONObject payloads = getPayloads();
        // 解析 Token 获取 jti(JWT ID) 和 exp(过期时间)
        String jti = payloads.getStr(JWTPayload.JWT_ID);
        Long expiration = payloads.getLong(JWTPayload.EXPIRES_AT); // 过期时间(秒)
        // 如果exp存在，则计算Token剩余有效时间
        if (expiration != null) {
            long currentTimeSeconds = System.currentTimeMillis() / 1000;
            if (expiration < currentTimeSeconds) {
                redisTemplate.delete(SecurityConstants.TOKEN_TENANT_PREFIX + jti);
            }
            // 将Token的jti加入黑名单，并设置剩余有效时间，使其在过期后自动从黑名单移除
            long ttl = expiration - currentTimeSeconds;
            redisTemplate.opsForValue().set(SecurityConstants.TOKEN_TENANT_PREFIX + jti, tenantId, ttl, TimeUnit.SECONDS);
        }
    }

    private JSONObject getPayloads() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        token = token.substring(SecurityConstants.JWT_TOKEN_PREFIX.length());
        return JWTUtil.parseToken(token).getPayloads();
    }

    public Long getTenant() {
        JSONObject payloads = getPayloads();
        // 解析 Token 获取 jti(JWT ID) 和 exp(过期时间)
        String jti = payloads.getStr(JWTPayload.JWT_ID);
        Long expiration = payloads.getLong(JWTPayload.EXPIRES_AT); // 过期时间(秒)
        // 如果exp存在，则计算Token剩余有效时间
        if (expiration != null) {
            return null;
        } else {
            return (Long) redisTemplate.opsForValue().get(SecurityConstants.TOKEN_TENANT_PREFIX + jti);
        }

    }
}
